<template>
  <div :class="prefixCls" class="relative h-full">
    <Spin wrapperClassName="h-full basic-model-spin" :delay="100" :spinning="loading">
      <FormTitle :text="title" class="model-title" v-if="title" />
      <BasicTable @register="registerTable" @change="handleChangeSearch">
        <template #tableTitle v-if="isShowTop">
          <slot name="headBtn" v-bind="{ tableItems, tableFn }">
            <div class="flex flex-1 items-center justify-between">
              <template v-for="(btns, _) in tableItems" :key="_">
                <ButtonActions
                  :tableFn="tableFn"
                  @add="handleAddFn"
                  @flow-add="openModalFn"
                  :data="btns"
                  @delete="
                    () => {
                      handleBatchDel(comParams, tableFn);
                    }
                  "
                  @custom="customFnForApi"
                  @custom-component="handleCustomComponent"
                />
              </template>
            </div>
          </slot>
        </template>
        <template #bodyCell="{ column, record }">
          <template v-if="column.key === 'rightAction'">
            <slot
              name="actions"
              v-bind="{
                actions: centerRightBtns,
                record,
                comParams,
                reload,
                openModalFn,
                setModalPropsFn,
                importFile,
                tableFn,
                handleCustomComponent,
              }"
            >
              <TableAction
                :record="record"
                :dropDownActionsFn="dropDownActionsFn"
                :actionsFn="actionsFn"
              />
            </slot>
          </template>
        </template>
      </BasicTable>
    </Spin>
    <FormModal @register="registerModal" @success="handleSuccess" />
    <FormDrawer @register="registerDrawer" @success="handleSuccess" />
    <ModelDesign :classify="1" :modelId="modelId" @success="init" />
    <BasicImport
      ref="basicImport"
      :api="
        async (params, fn) => {
          const callback = await handleImportApi(btnItem, tableFn);
          return await callback(params, fn);
        }
      "
      @success="handleSuccess"
    />

    <CustomModelComponent
      @register="handleCustomComponentFn"
      @success="handleSuccess"
      @cancel="handleSuccess"
    />
  </div>
</template>

<script lang="ts" setup name="BasicModel">
  import { ref, unref, computed, inject, watch, Ref, nextTick } from 'vue';

  import { Spin } from 'ant-design-vue';

  import {
    BasicTable,
    useTable,
    TableAction,
    ActionItem,
    FormProps,
    TableRowSelection,
    BasicTableProps,
    FormSchema,
  } from '/@/components/Table';

  import ButtonActions from './components/ButtonActions.vue';
  import FormDrawer from './components/FormDrawer.vue';
  import FormModal from './components/FormModal.vue';
  import ModelDesign from './components/ShowModelDesign.vue';
  import FormTitle from '/@/components/HFormTitle';
  import CustomModelComponent from './components/customCom/index.vue';

  import QueryString from 'qs';

  import { useDrawer } from '/@/components/Drawer';
  import { useModal } from '/@/components/Modal';
  import { useDebounceFn } from '@vueuse/core';
  import { useUserStore } from '/@/store/modules/user';
  import { useMessage } from '/@/hooks/web/useMessage';

  import { useRouter } from 'vue-router';
  import { useDesign } from '/@/hooks/web/useDesign';
  import { useActions } from './hooks/useActions';
  import {
    getRowKeys,
    handleBatchDel,
    customFnForApi,
    handleImportApi,
    getRealApi,
    customComponentAboutFn,
  } from './hooks/functionSet';
  import { getCSSValue } from '/@/utils';

  import { beforeFetch, useSearchForm, handleSearchInfoFn } from './hooks/useTableSearch';
  import getColumn from './hooks/setColumn';
  import { BTN_POSITION, DIALOG_TYPE } from '/@/views/config-center/model-design/model';
  import { ModalParams, CustomFnObjType, CUSTOM_FN_TYPE } from './types';

  import {
    getModuleListInfoApi, // 模块id查配置
    getGetModuleCommonListApi, // 模块id+模型id查数据
    getGetModuleCommonListPreviewApi,
    saveUserProfileApi,
    getModelInfoApi, // 模型id查配置 预览时使用
  } from '/@/api/config-center/model-design';
  import BasicImport from '/@/components/ImportButton/src/BasicImport.vue';

  let setComponentName = inject('setComponentName') as Fn;
  const { prefixCls } = useDesign('BasicModel');

  const props = withDefaults(
    defineProps<{
      modalParams?: ModalParams;
      tableProps?: Partial<BasicTableProps>;
    }>(),
    {
      modalParams: () => ({}),
      tableProps: () => ({}),
    },
  );

  // const emit = defineEmits(['register']);

  const loading = ref(true);
  const userStore = useUserStore();
  const { createMessage } = useMessage();
  let config: Ref<Indexable> = ref({});

  let customFnObj: CustomFnObjType = {};

  // eslint-disable-next-line vue/no-setup-props-destructure
  const { modalParams, tableProps } = props;
  const isReload =
    modalParams.searchDefaultParam && Object.keys(modalParams.searchDefaultParam).length;
  const { currentRoute } = useRouter();
  const route = unref(currentRoute);

  const moduleId = ref(modalParams.moduleId || (route.meta.moduleId as string));
  const modelId = ref(modalParams.modelId || (route.meta.modelId as string));

  let query = {
    ...(route.meta.query as Indexable),
  };
  const modelInfo = ref();
  const isTreeTable = ref(false);
  setComponentName('Module' + unref(moduleId));

  const complexParams = computed(() => {
    const {
      record,
      param,
      query: mQuery,
      parentQuery,
      parentParam,
      dynamicParams,
    } = props.modalParams;

    const pRet = getRowKeys(parentParam || '', record || {});
    const selfParam = getRowKeys(param || dynamicParams || '', record || {});
    const windowParam = Object.assign(pRet, selfParam, record || {});

    const windowQuery = Object.assign(
      query,
      QueryString.parse(parentQuery!, {
        ignoreQueryPrefix: true,
      }),
      QueryString.parse(mQuery!, {
        ignoreQueryPrefix: true,
      }),
      record || {},
    );

    return { windowParam, windowQuery };
  });

  const comParams = computed(() => {
    return {
      moduleId: unref(moduleId),
      tableModelId: unref(modelId),
      primaryKey: modelInfo.value.primaryKey,
      complexParams: unref(complexParams),
    };
  });

  const title = computed(() => {
    const { showTitle } = props.modalParams || {};
    return showTitle && modelInfo.value && modelInfo.value.title;
  });

  // ---------- init start ---------

  const [registerTable, tableFn] = useTable({
    useSearchForm: false,
    showTableSetting: false,
    bordered: false,
    showIndexColumn: false,
  });
  const { reload, setLoading, setProps, getForm } = tableFn;
  const delyReload = useDebounceFn(reload, 200);

  watch(
    () => [props.modalParams.moduleId, props.modalParams.modelId],
    ([mId, moId]) => {
      if (mId || moId) {
        if (moduleId.value === mId && modelId.value === moId) {
          return;
        }
        moduleId.value = mId!;
        modelId.value = moId!;

        init();
      }
    },
  );
  watch(
    () => [props.modalParams.param, props.modalParams.query],
    () => {
      delyReload();
    },
  );
  init();

  async function getInitApi() {
    const { isComplex, preview } = props.modalParams;

    if (isComplex && preview) {
      return await getModelInfoApi(unref(modelId));
    }
    const params = {
      moduleId: unref(moduleId),
      modelId: unref(modelId),
    };
    return getModuleListInfoApi(params);
  }

  const StepMenuDrawer = ref();

  async function init() {
    try {
      loading.value = true;
      const data = await getInitApi();
      modelInfo.value = data.tableDesignInfo;
      const {
        titles,
        pageSize,
        tableButtons,
        checkbox = false,
        tableSetting,
        plainOptions, // 排序使用的高级功能字段
        tableType,
      } = data.tableDesignInfo;
      isTreeTable.value = tableType === 'tree';
      await setSearchForm(titles);

      const columns = await getColumn(titles, plainOptions);
      setComParms(titles, tableButtons);

      setButtons(tableButtons);

      let scroll = {};

      // 是否多选
      let rowSelection: TableRowSelection | undefined = undefined;
      if (checkbox) {
        rowSelection = {
          type: 'checkbox',
        };
      }
      const pagination = unref(isTreeTable) || pageSize === 0 ? false : { pageSize };

      setProps({
        ...tableProps,
        scroll,
        columns,
        isTreeTable: unref(isTreeTable),
        api: getPageListApi,
        beforeFetch,
        handleSearchInfoFn,
        rowSelection,
        actionColumn: setTableAction(),
        pagination,
        showTableSetting: !!tableSetting,
        tableSetting,
        settingSave: saveColumnSort,
        clearSelectOnPageChange: true,
      });
      if (isReload) return;

      await reload();
    } catch (e) {
      console.log(
        '%ce===>203： ',
        'background: rgb(23, 197, 237,.6); color: #ff5023; font-size:18px;font-weight:700',
        e,
      );

      throw e;
    } finally {
      setTimeout(() => {
        loading.value = false;
      }, 0.1 * 1000);
    }
  }

  let orderby: any[] = [];
  let oldConditions: Indexable = {};

  async function getPageListApi(data: Indexable = { current: 1, size: 10 }) {
    setLoading(true);
    // 处理分页查询丢失数据问题
    if (data.conditions) {
      oldConditions = data.conditions;
    } else {
      data.conditions = oldConditions;
    }

    const { windowQuery, windowParam } = unref(complexParams);

    const params = {
      current: 1,
      size: 10,
      ...data,
      orderby,
      query: {
        ...query,
        ...windowQuery,
      },
      param: {
        ...windowQuery,
        ...windowParam,
      },
    };

    const ret = await getListApi(params);

    return ret;
  }

  async function saveColumnSort(plainOptions) {
    const profile = {
      userId: userStore.getUserInfo?.userId,
      moduleId: unref(moduleId),
      plainOptions,
    };

    // userId
    // moduleId
    await saveUserProfileApi(profile);
    createMessage.success('保存成功');
  }
  async function handleChangeSearch(...arg) {
    const sortInfo = arg[2];
    const orderType = {
      ascend: 1,
      descend: 0,
    };

    if (sortInfo.field) {
      const asc = orderType[sortInfo.order];
      const oldSort = orderby.find((el) => el.dataIndex === sortInfo.field);
      if (oldSort) {
        oldSort.asc = asc;
        return;
      } else {
        orderby.push({ dataIndex: sortInfo.field, asc });
      }
    }
  }

  function setComParms(titles, tableButtons) {
    titles.forEach((bt) => {
      bt._comParams = comParams.value;
      bt._tableFn = tableFn;
    });
    tableButtons.forEach((bt) => {
      if (!bt.moduleId) {
        bt.moduleId = unref(moduleId);
      }
      bt._comParams = comParams.value;
    });
  }

  // 列表查询配置
  async function setSearchForm(titles: any[]) {
    const data = titles.filter((el) => el.searchType > 0);

    if (!data.length) {
      return;
    }
    const schemas: FormSchema[] = await useSearchForm(data, tableFn as any);

    // let setSchemasObj = {};
    // if (modalParams.searchDefaultParam?.length) {
    //   const searchDefaultParam = modalParams.searchDefaultParam;
    //   schemas.map((i) => {
    //     for (let j = 0; j < searchDefaultParam.length; j++) {
    //       if (searchDefaultParam[j].field === i.field) {
    //         // i.defaultValue = searchDefaultParam[j].value;
    //         setSchemasObj[i.field] = searchDefaultParam[j].value;
    //         // setFieldsValue({ [i.field]: searchDefaultParam[j].value });
    //       }
    //     }
    //   });
    // }

    const { submit, setFieldsValue } = getForm();
    const formConfig: FormProps = {
      schemas: schemas,
      compact: false,
      autoSubmitOnEnter: true,
      labelWidth: '100%',
      rowProps: { gutter: 16 },
    };
    setProps({ formConfig, useSearchForm: true });

    if (isReload) {
      nextTick(() => {
        setFieldsValue(modalParams.searchDefaultParam);
        submit();
      });
    }
  }

  // 列表接口配置
  async function getListApi(params: Indexable) {
    if (modelInfo.value.apiCode) {
      return await getRealApi({
        params,
        apiCode: modelInfo.value.apiCode,
      });
    }
    const { preview } = modalParams;
    if (preview) return await getGetModuleCommonListPreviewApi(unref(modelId), params);
    const moduleParams = {
      moduleId: unref(moduleId),
      modelId: unref(modelId),
    };
    return await getGetModuleCommonListApi(moduleParams, params);
  }
  // ---------- init end ---------

  // ---------- 按钮配置 start ---------
  const topLeftBtns = ref<any[]>([]);
  const topCenterBtns = ref<any[]>([]);
  const topRightBtns = ref<any[]>([]);
  const centerLeftBtns = ref<any[]>([]);
  const centerRightBtns = ref<any[]>([]);
  const centerRightRetractBtns = ref<any[]>([]);

  const tableItems = computed(() => {
    return [unref(topLeftBtns), unref(topCenterBtns), unref(topRightBtns)];
  });

  const isShowTop = computed(() => {
    return unref(topLeftBtns).length || unref(topCenterBtns).length || unref(topRightBtns).length;
  });

  function setButtons(btns: any[]) {
    // 表格上下按钮位置
    topLeftBtns.value = btns.filter((el) => el.location === BTN_POSITION.TOP_LEFT);
    topCenterBtns.value = btns.filter((el) => el.location === BTN_POSITION.TOP_CENTER);
    topRightBtns.value = btns.filter((el) => el.location === BTN_POSITION.TOP_RIGHT);

    // 表格内部操作按钮
    centerLeftBtns.value = btns.filter((el) => el.location === BTN_POSITION.CENTER_LEFT);
    centerRightBtns.value = btns.filter(
      (el) => el.location === BTN_POSITION.CENTER_RIGHT && el.retractType !== 1,
    );

    // 表格内部收起按钮
    centerRightRetractBtns.value = btns.filter(
      (el) => el.location === BTN_POSITION.CENTER_RIGHT && el.retractType === 1,
    );
  }

  function setTableAction() {
    const centerRightLen = unref(centerRightBtns).length;
    const centerRightRetractBtnsLens = unref(centerRightRetractBtns).length ? 1 : 0;

    let col: Indexable | undefined = undefined;
    if (centerRightLen || centerRightRetractBtnsLens) {
      col = {
        width: 70 * centerRightLen + centerRightRetractBtnsLens * 30 + 'px',
        dataIndex: 'rightAction',
        title: '操作',
        fixed: 'right',
      };
    }

    return col;
  }

  function actionsFn(record: Indexable): ActionItem[] {
    const params = {
      ...unref(comParams),
      record,
    };
    const res = useActions(centerRightBtns, params, [
      reload,
      setModalPropsFn,
      openModalFn,
      () => {},
      importFile,
      handleCustomComponent,
      () => tableFn,
    ]);
    return res;
  }

  function dropDownActionsFn(record: Indexable): ActionItem[] {
    const params = {
      ...unref(comParams),
      record,
    };
    const res = useActions(centerRightRetractBtns, params, [
      reload,
      setModalPropsFn,
      openModalFn,
      () => {},
      importFile,
      handleCustomComponent,
      () => tableFn,
    ]);

    return res;
  }

  // ---------- 按钮配置 end ---------

  // ---------- 通用弹框配置 start ---------
  const [registerModal, { openModal, setModalProps }] = useModal();
  const [registerDrawer, { openDrawer, setDrawerProps }] = useDrawer();

  async function handleAddFn(btnItem: Indexable) {
    setModalPropsFn(btnItem);
    openModalFn(btnItem);
  }

  // 自定义组件事件
  const handleCustomComponent = (val, tabFn?: Fn) => {
    setModalPropsFn(val);

    if (val.hanldRow) {
      // 行内点击
      customComponentAboutFn(
        {
          openModel: customFnObj[CUSTOM_FN_TYPE[val.dialogType]],
          tabFn: tabFn,
          ...val,
        },
        val.record,
      );
    } else {
      customComponentAboutFn({
        openModel: customFnObj[CUSTOM_FN_TYPE[val.dialogType]],
        tabFn: tabFn,
        ...val,
      });
    }
  };
  const handleCustomComponentFn = (FnObj: CustomFnObjType) => {
    customFnObj = FnObj;
  };

  function setModalPropsFn(btnItem) {
    const { width: w, placement } = btnItem;
    const width = getCSSValue(w, '60%');

    switch (btnItem.dialogType) {
      case DIALOG_TYPE.drawer:
        setDrawerProps({
          width,
          destroyOnClose: true,
          placement: placement || 'right',
        });
        break;
      case DIALOG_TYPE.modal:
        setModalProps({ width, destroyOnClose: true });
        break;
    }
  }
  function openModalFn(btnItem: Indexable) {
    config.value = btnItem;
    if (btnItem.componentName === 'StepMenuDrawerA') {
      StepMenuDrawer.value.handleDrawer(btnItem);
      return;
    }
    switch (btnItem.dialogType) {
      case DIALOG_TYPE.drawer:
        openDrawer(true, btnItem);
        break;
      case DIALOG_TYPE.modal:
        openModal(true, btnItem);
        break;

      default:
    }
  }

  // ---------- 通用弹框配置 end ---------
  async function handleSuccess() {
    reload();
  }

  const basicImport = ref<any>(null);
  const btnItem = ref(null);
  function importFile(btns) {
    btnItem.value = btns;
    basicImport.value.handleModal();
  }
</script>
<style lang="less" scoped>
  .model-title {
    padding: 16px 8px 0;
    background-color: @component-background;
  }

  .basic-model-spin {
    ::v-deep(.ant-spin-container) {
      height: 100%;
    }
  }
</style>
